import { app, shell, BrowserWindow, ipcMain } from 'electron'
import UDPServer from './udp.server'

import FramePacker from './FramePacker'
import { jspack } from 'jspack'
import { isEqual } from 'lodash'


export default class TestServer {
  private _udpServer: UDPServer
  private _framePacker: FramePacker
  constructor(udpServer: UDPServer, framePacker: BrowserWindow) {
    this._udpServer = udpServer
    this._framePacker = framePacker
    this._frameHeader = 0xcc
    this._frameTrailer = 0xcc
    this.bindEvent()
  }


  pack(format, params) {
    const header = jspack.Pack('>B', [this._frameHeader])
    let msgBuffer = header.concat(jspack.Pack(format, params))
    const footer = jspack.Pack('>B', [this._frameTrailer])
    msgBuffer = msgBuffer.concat(footer)
    return Buffer.from(msgBuffer)
  }

  mapMessage(message, { acceptFields }) {
    return Object.fromEntries(acceptFields.map((key, index) => [key, message[index]]))
  }

  unpack(buffer, format) {

    const header = jspack.Unpack('>B', buffer)
    if (!isEqual(header, jspack.Pack('>B', [this._frameHeader]))) {
      return
    }
    const frameTrailer = buffer[buffer.length - 1]
    if (!isEqual(frameTrailer, this._frameTrailer)) {
      return
    }
    return jspack.Unpack(format, buffer)
  }


  bindEvent() {
    ipcMain.handle('NVRAM_TEST', async (event, params) => {
      const acceptFields = ['header', 'type', 'cmd', 'state', 'startArea', 'middleArea', 'endArea', 'size','computerId', 'cpuId', 'trailer']
      const parser = (msg, rinfo) => {
        const message =  this.unpack(msg, '>BBBBIIIIBBB')
        if(!message) {
          return
        }
        return Object.fromEntries(acceptFields.map((key, index) => [key, message[index]]))
      }
      const  acceptChecker =  (data = {}) => {
        return (message) => {
          if(!message){
            return false
          }
          return message.cmd === data.cmd && message.computerId === data.computerId && message.cpuId === data.cpuId
        }
      }

      const buffer = this.pack('>BBBB', [0x00, params.cmd,  params.computerId, params.cpuId ])
      const link = params.link;

      const result = await this._udpServer.sendAsync(link.port, link.host, buffer, { parser, acceptChecker: acceptChecker(params) })
      return result
    })

    ipcMain.handle('DDR_TEST', async (event, params) => {
      const acceptFields = ['header', 'type', 'cmd', 'state', 'area', 'size', 'computerId', 'cpuId', 'trailer']
      const parser = (msg, rinfo) => {
        const message =  this.unpack(msg, '>BBBBIIBBB')
        if(!message) {
          return
        }
        return Object.fromEntries(acceptFields.map((key, index) => [key, message[index]]))
      }
      const  acceptChecker = (data = {}) => {
        return (message) => {
          if(!message){
            return false
          }
          return message.cmd === data.cmd && message.computerId === data.computerId && message.cpuId === data.cpuId
        }
      }

      const buffer = this.pack('>BBBB', [0x00, params.cmd,  params.computerId, params.cpuId ])
      const link = params.link;
      const result = await this._udpServer.sendAsync(link.port, link.host, buffer, { parser, acceptChecker: acceptChecker(params) })
      return result
    })
  }
}
